react 怎么阻止事件冒泡? | 您所在的位置:网站首页 › react 添加事件 › react 怎么阻止事件冒泡? |
react的事件都是合成事件,所有事件最后都是代理到document上面。(在react17中不再是代理到document,而是react组件树的容器节点) 而你在合成事件内调用e.stopPropagation(),也只能阻止react的合成事件的冒泡触发,不能阻止你在document上绑定的原生事件。 用下面的例子就很容易理解 import React, { useEffect, useRef } from 'react'; export default function Demo() { const appRef = useRef(); const btnRef = useRef(); useEffect(() => { window.addEventListener('click', function () { console.log('window click') }) document.addEventListener('click', function () { console.log('document click') }) btnRef.current.addEventListener('click', function () { console.log('btn click'); }) appRef.current.addEventListener('click', function () { console.log('app click'); }) }, []); function onBtnClick(e) { console.log('react button click'); } function onAppClick(e) { console.log('react app click'); } return ( 按钮 ) }不添加任何阻止冒泡逻辑的时候,执行顺序如下 btn clickapp clickreact button clickreact app clickdocument clickwindow click 如果我们在按钮的点击事件中添加react阻止冒泡的逻辑 ... function onBtnClick(e) { e.stopPropagation(); console.log('react button click'); } ...可以发现,react合成事件的冒泡被阻止了。所以,react app click没有被打印,但是原生事件没有被阻止,仍然打印 这说明react事件中e.stopPropagation()只能阻止react的合成事件的冒泡。 btn clickapp clickreact button clickdocument click 然后我们换成e.nativeEvent.**stopImmediatePropagation**() function onBtnClick(e: any) { e.nativeEvent.stopImmediatePropagation() console.log('react button click') } 执行结果如下,可以发现这个api就能达到我们的要求,做到不触发document上的点击事件。 btn clickapp clickreact button clickreact app click 02.stopImmediatePropagation Event接口的**stopImmediatePropagation()**方法阻止监听同一事件的其他事件监听器被调用。 如果多个事件监听器被附加到相同元素的相同事件类型上,当此事件触发时,它们会按其被添加的顺序被调用。如果在其中一个事件监听器中执行 stopImmediatePropagation() ,那么剩下的事件监听器都不会被调用。 也就是说这个事件会阻止后续添加的事件的执行。 因此当点击事件执行,然后冒泡到document的时候,会阻止document上其他函数的执行。所以达成了我们想要的效果。 03.总结 可以得出以下3种方法在react里阻止事件冒泡 1.通过原生事件阻止事件冒泡,阻止dom原生事件。 btnRef.current.addEventListener('click', function (e) { e.stopPropagation(); console.log('btn click');}) 2.使用e.nativeEvent.stopImmediatePropagation()阻止document上同类事件的调用。 function onBtnClick(e) { // e.stopPropagation(); e.nativeEvent.stopImmediatePropagation(); console.log('react button click');} 按钮 3.在window上绑定事件, 因为react16把所有事件都代理到document,window的顺序位于document之后,所以是可以阻止(react jsx事件回调里的e.stopPropagation 只能阻止react 在document上绑定的代理事件的冒泡行为。) 04.实践 第一条不实用,相当于我们在react里面,不用react的合成事件,而增加了原生代码的比例。 第三条实际上没有阻止到document上点击事件的触发, 因此还是用stopImmediatePropagation+stopPropagation的方式,这样能阻止react合成事件冒泡,又能阻止document上事件的执行。 因此最后可以编写下面的通用函数来阻止冒泡 import { SyntheticEvent } from 'react' /** * 取消事件冒泡 * @param e */ export default function cancelBubble(e: SyntheticEvent) { e.stopPropagation() e.nativeEvent.stopImmediatePropagation() } |
CopyRight 2018-2019 实验室设备网 版权所有 |